This notebook is based on covid_19.Rmd. I created the present notebook because there was already too much information in covid_19.Rmd.
Methodology
- We know the number of people dead.
- We have estimates of how many people die from the disease.
- Assumes that the mean number of days from infection to death is 14 (see
covid_infection_estimates2.Rmd for estimates using 28 days as the assumption)
1. Import files and packages
library(tidyr)
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(stringr)
library(readr)
library(lubridate)
Attaching package: ‘lubridate’
The following object is masked from ‘package:base’:
date
deaths <- read_csv('covid_19_deaths.csv')
Parsed with column specification:
cols(
Date = [34mcol_date(format = "")[39m,
`UK Deaths` = [32mcol_double()[39m,
`Global Deaths` = [32mcol_double()[39m
)
2. inspect and clean the data
deaths <- deaths %>% mutate(infection_date=Date-days(14))
deaths <- deaths %>% rename(death_date=Date, deaths=`UK Deaths`)
uk_data <- deaths %>% select(-`Global Deaths`)
head(uk_data)
3. Add estimates of infections (three columns, showing a low, middle and a high estimate)
#add columns for various estimated death rates (0.1%, 0.5%, 1%, 2%, 3%)
uk_data <- uk_data %>% mutate(estimated_uk_cases_tenth=(deaths*1000))
uk_data <- uk_data %>% mutate(estimated_uk_cases_one=(deaths*100))
uk_data <- uk_data %>% mutate(estimated_uk_cases_two=(deaths*50))
uk_data
NA
4. clean the data again (reorder the columns)
# order should be two, one, tenth (as this shows the min-max range better)
5. create a new table that starts at 22nd March (since uk_data infection_date went up to 21st March at the time I created this code)
# using only estimates of 1% death rate and growth rate of doubling every 3-4 days (which means quadrupling in a week)
predictor <- function(previous_value) {
predicted_value <- previous_value * 1.25
return(predicted_value)
}
# create predictions for each date
twentyTwoMarch <- 1.25 * 360500
twentyThreeMarch <- predictor(twentyTwoMarch)
twentyFourMarch <- predictor(twentyThreeMarch)
twentyFiveMarch <- predictor(twentyFourMarch)
twentySixMarch <- predictor(twentyFiveMarch)
twentySevenMarch <- predictor(twentySixMarch)
twentyEightMarch <- predictor(twentySevenMarch)
twentyNineMarch <- predictor(twentyEightMarch)
thirtyMarch <- predictor(twentyNineMarch)
thirtyOneMarch <- predictor(thirtyMarch)
oneApril <- predictor(thirtyOneMarch)
twoApril <- predictor(oneApril)
threeApril <- predictor(twoApril)
fourApril <- predictor(threeApril)
fiveApril <- predictor(fourApril)
sixApril <- predictor(fiveApril)
sevenApril <- predictor(sixApril)
eightApril <- predictor(sevenApril)
nineApril <- predictor(eightApril)
tenApril <- predictor(nineApril)
elevenApril <- predictor(tenApril)
twelveApril <- predictor(elevenApril)
thirteenApril <- predictor(twelveApril)
fourteenApril <- predictor(thirteenApril)
fifteenApril <- predictor(fourteenApril)
sixteenApril <- predictor(fifteenApril)
seventeenApril <- predictor(sixteenApril)
eighteenApril <- predictor(seventeenApril)
nineteenApril <- predictor(eighteenApril)
twentyApril <- predictor(nineteenApril)
twentyoneApril <- predictor(twentyApril)
twentytwoApril <- predictor(twentyoneApril)
twentythreeApril <- predictor(twentytwoApril)
twentyfourApril <- predictor(twentythreeApril)
# create vectors to populate the columns
date <- as.Date(c("2020-03-22", "2020-03-23", "2020-03-24", "2020-03-25", '2020-03-26','2020-03-27', '2020-03-28', '2020-03-29', '2020-03-30', '2020-03-31', "2020-04-01", "2020-04-02", "2020-04-03", "2020-04-04", "2020-04-05", "2020-04-06", "2020-04-07", "2020-04-08", "2020-04-09", "2020-04-10", "2020-04-11", "2020-04-12", "2020-04-13", "2020-04-14", "2020-04-15", "2020-04-16", "2020-04-17", "2020-04-18", "2020-04-19", "2020-04-20", "2020-04-21", "2020-04-22", "2020-04-23", "2020-04-24"))
estimated_infections_no_action <- c(twentyTwoMarch, twentyThreeMarch, twentyFourMarch, twentyFiveMarch,twentySixMarch, twentySevenMarch, twentyEightMarch, twentyNineMarch, thirtyMarch, thirtyOneMarch, oneApril, twoApril, threeApril, fourApril, fiveApril, sixApril, sevenApril, eightApril, nineApril, tenApril, elevenApril, twelveApril, thirteenApril, fourteenApril, fifteenApril, sixteenApril, seventeenApril, eighteenApril, nineteenApril, twentyApril, twentyoneApril, twentytwoApril, twentythreeApril, twentyfourApril)
# create the data frame
predicted_infections <- data.frame(date, estimated_infections_no_action)
# tidy the estimated_infections column
#predicted_infections <- predicted_infections %>% mutate(estimated_infections=format(estimated_infections, big.mark = ","))
# inspect the data frame
predicted_infections
6. Create another dataframe to estimate the impact of social distancing on the estimate
# create a function that uses a growth rate of 1.125 - half of the 25%. This is the estimate for the not-yet-lockdown that existed up to 23rd March. So, the estimate assumes that the social distancing measures reduced the infection rate by a half.
half_predictor <- function(previous_value) {
predicted_value <- previous_value * 1.125
return(predicted_value)
}
# create a function that uses a growth rate of 1.0625 - quarter of the 25%. This is the estimated impact of the lockdown implemented by the UK government on 23rd March (but since the lockdown was announced in the evening, and it would take a full day for its effects to be felt in statistics, I will assume that its effects began on 25th March).
lockdown_predictor <- function(previous_value) {
predicted_value <- previous_value * 1.0625
return(predicted_value)
}
# create predictions for each date
twentyTwoMarch <- 1.125 * 360500
twentyThreeMarch <- half_predictor(twentyTwoMarch)
twentyFourMarch <- half_predictor(twentyThreeMarch)
twentyFiveMarch <- lockdown_predictor(twentyFourMarch)
twentySixMarch <- lockdown_predictor(twentyFiveMarch)
twentySevenMarch <- lockdown_predictor(twentySixMarch)
twentyEightMarch <- lockdown_predictor(twentySevenMarch)
twentyNineMarch <- lockdown_predictor(twentyEightMarch)
thirtyMarch <- lockdown_predictor(twentyNineMarch)
thirtyOneMarch <- lockdown_predictor(thirtyMarch)
oneApril <- lockdown_predictor(thirtyOneMarch)
twoApril <- lockdown_predictor(oneApril)
threeApril <- lockdown_predictor(twoApril)
fourApril <- lockdown_predictor(threeApril)
fiveApril <- lockdown_predictor(fourApril)
sixApril <- lockdown_predictor(fiveApril)
sevenApril <- lockdown_predictor(sixApril)
eightApril <- lockdown_predictor(sevenApril)
nineApril <- lockdown_predictor(eightApril)
tenApril <- lockdown_predictor(nineApril)
elevenApril <- lockdown_predictor(tenApril)
twelveApril <- lockdown_predictor(elevenApril)
thirteen_April <- lockdown_predictor(twelveApril)
fourteen_April <- lockdown_predictor(thirteen_April)
fifteen_April <- lockdown_predictor(fourteen_April)
sixteen_April <- lockdown_predictor(fifteen_April)
seventeen_April <- lockdown_predictor(sixteen_April)
eighteen_April <- lockdown_predictor(seventeen_April)
nineteen_April <- lockdown_predictor(eighteen_April)
twenty_April <- lockdown_predictor(nineteen_April)
twentyone_April <- lockdown_predictor(twenty_April)
twentytwo_April <- lockdown_predictor(twentyone_April)
twentythree_April <- lockdown_predictor(twentytwo_April)
twentyfour_April <- lockdown_predictor(twentythree_April)
# create vectors to populate the columns
date <- as.Date(c("2020-03-22", "2020-03-23", "2020-03-24", "2020-03-25", '2020-03-26','2020-03-27', '2020-03-28', '2020-03-29', '2020-03-30', '2020-03-31', "2020-04-01", "2020-04-02", "2020-04-03", "2020-04-04", "2020-04-05", "2020-04-06", "2020-04-07", "2020-04-08", "2020-04-09", "2020-04-10", "2020-04-11", "2020-04-12", "2020-04-13", "2020-04-14", "2020-04-15", "2020-04-16", "2020-04-17", "2020-04-18", "2020-04-19", "2020-04-20", "2020-04-21", "2020-04-22", "2020-04-23", "2020-04024"))
estimated_infections_lockdown <- c(twentyTwoMarch, twentyThreeMarch, twentyFourMarch, twentyFiveMarch,twentySixMarch, twentySevenMarch, twentyEightMarch, twentyNineMarch, thirtyMarch, thirtyOneMarch, oneApril, twoApril, threeApril, fourApril, fiveApril, sixApril, sevenApril, eightApril, nineApril, tenApril, elevenApril, twelveApril, thirteen_April, fourteen_April, fifteen_April, sixteen_April, seventeen_April, eighteen_April, nineteen_April, twenty_April, twentyone_April, twentytwo_April, twentythree_April, twentyfour_April)
# create the data frame
lockdown_infection_rates <- data.frame(date, estimated_infections_lockdown)
# tidy the estimated_infections column
#lockdown_infection_rates <- lockdown_infection_rates %>% mutate(estimated_infections_lockdown=format(estimated_infections_lockdown, scientific = FALSE))
# inspect the data frame
lockdown_infection_rates
NA
## 7. Merge the two prediction dataframes
compared_infections <- predicted_infections %>% bind_cols(estimated_infections_lockdown=lockdown_infection_rates$estimated_infections_lockdown)
compared_infections
NA
8. Tidy the data
#compared_infections <- compared_infections %>% mutate(estimated_infections=format(estimated_infections, big.mark = ","))
#compared_infections <- compared_infections %>% mutate(estimated_infections_lockdown=as.numeric(estimated_infections_lockdown))
#compared_infections <- compared_infections %>% mutate(estimated_infections_lockdown=format(estimated_infections_lockdown, big.mark = ","))
compared_infections
The above table shows a huge possible effect of lockdown, but still the number of infections is in seven figures. However, this does not indicate how many people might be infected at any given time. Rather, it estimates how many people might have been infected in total, and so includes people who no longer have the disease (that is, people who have recovered or died).
9. Predicted deaths based on these estimates
Working backwards from these estimates, compare the predicted deaths.
# first, put the columns back to numeric format
#compared_infections_and_deaths <- compared_infections %>% mutate(estimated_infections=as.numeric(estimated_infections))
compared_infections_and_deaths <- compared_infections %>% mutate(estimated_deaths_no_action=0.01*estimated_infections_no_action)
compared_infections_and_deaths <- compared_infections_and_deaths %>% mutate(estimated_deaths_lockdown=0.01*estimated_infections_lockdown)
compared_infections_and_deaths
Note that the estimates_deaths and estimated_deaths_lockdown columns are not estimates for deaths on or up to the date in the relevant row. It is anticipated that deaths would occur some days or weeks after the date given in the table. For example, if the row for 2020-04-01 shows estimated_deaths_lockdown of 8336.703, that doesn’t mean 8336.703 people would have died by 2020-04-01. Rather, that figure would occur around two weeks after 2020-04-01 (so, approximately 2020-04-15). So, this suggests an additional column might be useful (date of predicted deaths) ymd(‘2019-12-01’) %m+% period(“1 month”)
compared_infections_and_deaths_dates <- compared_infections_and_deaths %>% mutate(death_date_14_days=as.Date(date + days(14)))
compared_infections_and_deaths_dates <- compared_infections_and_deaths_dates %>% mutate(death_date_7_days=as.Date(date + days(7)))
# add a column to review the results on a daily basis.
assess <- c("NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA")
compared_infections_and_deaths_dates <- compared_infections_and_deaths_dates %>% mutate(fourteen_day_assessment = assess)
Error: Column `fourteen_day_assessment` must be length 34 (the number of rows) or one, not 33
In what ways could these estimates and predictions go wrong? Or, what parts of the data could be inaccurate? * estimate of 1% death rate * estimate of time taken for lockdown to have an effect (I’ve said 14-21 days). Note that death_date_7_days shows the date if it takes 21 days to have an impact. * estimate of daily growth rates for minimal social distancing (1.125) and lockdown (1.0625)
update 6th April 2020 - it looks like my predictions may be a day or two out of synch with the stats. It’s hard to tell, as the number for lockdown and no action are fairly similar at this point. This means that it can be difficult to make an assessment: if the actual death toll is lower than the estimated_deaths_no_action column, is that due to the lockdown or the fact that it is a day or two behind? However, by around 10th April there should be a clearer picture.
- update 10th April 2020 - it now looks like my predictions might be 3 or 4 days out of synch with the stats. Look at the
death_date_14_days column, then add 4 days. Then look at the estimated_deaths_lockdown column. This seems to be closer to the actual death toll.
- update 11th April 2020: hospital deaths versus total deaths. My figures are for total deaths, but the UK provides figures for hospital deaths. One estimate I saw was that there were over 8000 deaths in hospital, plus an additional 1000 in care homes that were not included in the UK figures. I’m not sure whether or not the WHO figures cover only hospital deaths, but if they do then it would have an impact on my predictions.
- update 12th April 2020 - it now looks like my predictions are 5-6 days out of synch with the stats. So, look at the
death_date_14_days column, then add 5 or 6 days.
- update 13th April 2020 - the latest figures from the Office for National Statistics suggest that - in England and Wales, at least - deaths outside hospitals account for around 10% of all Covid-19-related deaths. Whilst I do not have the non-hospital figures for Scotland or Northern Ireland, I have no reason to believe they would be significantly different from England and Wales. So, I will assume that 10% of all Covid-19-related deaths in the UK happen outside of hospitals. This has an impact on how one reads the figures in my project. The figures I use in this project are from the WHO, which counts hospital deaths only. Therefore, for any given date, the number of deaths in my datasets should be considered to be only 90% of the true total. For instance, where my datasets state that the death toll on 11th April was 8958, we can estimate that the true death toll was actually around 10,000.
update 17th April - the figures are 6-7 days out.
library(ggplot2)
library(scales)
infectionsComparisonLine <- ggplot(compared_infections_and_deaths_dates, aes(x=date)) + geom_line(aes(y=estimated_infections_no_action), col = "steelblue") + geom_line(aes(y=estimated_infections_lockdown), col="darkred") + scale_y_continuous(labels=label_comma()) + geom_text(aes(x=as.Date("2020-04-13"), y = 50000000, label="No action")) + geom_text(x=as.Date("2020-04-13"), y = 5000000, label="Lockdown") + labs(title="Predicted infections (lockdown versus no action)", x='Date', y='Predicted Infections') + theme_classic()
infectionsComparisonLine

NA
deathsComparisonLine <- ggplot(compared_infections_and_deaths_dates, aes(x=death_date_7_days)) + geom_line(aes(y=estimated_deaths_no_action), col = "steelblue") + geom_line(aes(y=estimated_deaths_lockdown), col="darkred") + scale_y_continuous(labels=label_comma()) + geom_text(aes(x=as.Date("2020-04-21"), y = 500000, label="No action")) + geom_text(x=as.Date("2020-04-21"), y = 50000, label="Lockdown") + labs(title="Predicted Deaths (lockdown versus no action)", subtitle="estimates that it takes 3 weeks for measures to impact deaths", x='Date', y='Predicted Deaths') + theme_classic()
deathsComparisonLine

deathsComparisonLine <- ggplot(compared_infections_and_deaths_dates, aes(x=death_date_14_days)) + geom_line(aes(y=estimated_deaths_no_action), col = "steelblue") + geom_line(aes(y=estimated_deaths_lockdown), col="darkred") + scale_y_continuous(labels=label_comma()) + geom_text(aes(x=as.Date("2020-04-28"), y = 500000, label="No action")) + geom_text(x=as.Date("2020-04-28"), y = 50000, label="Lockdown") + labs(title="Predicted Deaths (lockdown versus no action)", subtitle="estimates that it takes 2 weeks for measures to impact deaths", x='Date', y='Predicted Deaths') + theme_classic()
deathsComparisonLine

library(plotly)
casesDeaths <- ggplot(compared_infections_and_deaths_dates, aes(x=estimated_infections_lockdown, y=estimated_deaths_lockdown)) + geom_point()
casesDeaths

interactive <- ggplotly(casesDeaths)
# fig <- interactive %>%
# plot_ly(
# x = ~x,
# y = ~y,
# frame = ~f,
# type = 'scatter',
# mode = 'markers',
# showlegend = F
# )
fig <- compared_infections_and_deaths_dates %>% plot_ly(x=~estimated_infections_lockdown, y=~estimated_deaths_lockdown, frame = ~date, type = 'scatter', mode='markers')
# fig <- fig %>% layout(
# xaxis = list(
# type = "log"
# )
# )
fig2 <- fig %>% animation_slider(currentvalue=list(prefix = "Date", font = list(color='red')))
fig2
NA
LS0tCnRpdGxlOiAiQ2FsY3VsYXRpbmcgdGhlIE51bWJlciBvZiBJbmZlY3Rpb25zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIG5vdGVib29rIGlzIGJhc2VkIG9uIGBjb3ZpZF8xOS5SbWRgLiBJIGNyZWF0ZWQgdGhlIHByZXNlbnQgbm90ZWJvb2sgYmVjYXVzZSB0aGVyZSB3YXMgYWxyZWFkeSB0b28gbXVjaCBpbmZvcm1hdGlvbiBpbiBgY292aWRfMTkuUm1kYC4KCiMjIE1ldGhvZG9sb2d5CiogV2Uga25vdyB0aGUgbnVtYmVyIG9mIHBlb3BsZSBkZWFkLiAKKiBXZSBoYXZlIGVzdGltYXRlcyBvZiBob3cgbWFueSBwZW9wbGUgZGllIGZyb20gdGhlIGRpc2Vhc2UuCiogQXNzdW1lcyB0aGF0IHRoZSBtZWFuIG51bWJlciBvZiBkYXlzIGZyb20gaW5mZWN0aW9uIHRvIGRlYXRoIGlzIDE0IChzZWUgYGNvdmlkX2luZmVjdGlvbl9lc3RpbWF0ZXMyLlJtZGAgZm9yIGVzdGltYXRlcyB1c2luZyAyOCBkYXlzIGFzIHRoZSBhc3N1bXB0aW9uKQoKCiMjIDEuIEltcG9ydCBmaWxlcyBhbmQgcGFja2FnZXMKYGBge3J9CmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShyZWFkcikKbGlicmFyeShsdWJyaWRhdGUpCmRlYXRocyA8LSByZWFkX2NzdignY292aWRfMTlfZGVhdGhzLmNzdicpCmBgYAoKCiMjIDIuIGluc3BlY3QgYW5kIGNsZWFuIHRoZSBkYXRhCmBgYHtyfQoKZGVhdGhzIDwtIGRlYXRocyAlPiUgbXV0YXRlKGluZmVjdGlvbl9kYXRlPURhdGUtZGF5cygxNCkpCmRlYXRocyA8LSBkZWF0aHMgJT4lIHJlbmFtZShkZWF0aF9kYXRlPURhdGUsIGRlYXRocz1gVUsgRGVhdGhzYCkKdWtfZGF0YSA8LSBkZWF0aHMgJT4lIHNlbGVjdCgtYEdsb2JhbCBEZWF0aHNgKQpoZWFkKHVrX2RhdGEpCmBgYAoKCiMjIDMuIEFkZCBlc3RpbWF0ZXMgb2YgaW5mZWN0aW9ucyAodGhyZWUgY29sdW1ucywgc2hvd2luZyBhIGxvdywgbWlkZGxlIGFuZCBhIGhpZ2ggZXN0aW1hdGUpCmBgYHtyfQojYWRkIGNvbHVtbnMgZm9yIHZhcmlvdXMgZXN0aW1hdGVkIGRlYXRoIHJhdGVzICgwLjElLCAwLjUlLCAxJSwgMiUsIDMlKQoKdWtfZGF0YSA8LSB1a19kYXRhICU+JSBtdXRhdGUoZXN0aW1hdGVkX3VrX2Nhc2VzX3RlbnRoPShkZWF0aHMqMTAwMCkpCnVrX2RhdGEgPC0gdWtfZGF0YSAlPiUgbXV0YXRlKGVzdGltYXRlZF91a19jYXNlc19vbmU9KGRlYXRocyoxMDApKQp1a19kYXRhIDwtIHVrX2RhdGEgJT4lIG11dGF0ZShlc3RpbWF0ZWRfdWtfY2FzZXNfdHdvPShkZWF0aHMqNTApKQp1a19kYXRhCgpgYGAKCgojIyA0LiBjbGVhbiB0aGUgZGF0YSBhZ2FpbiAocmVvcmRlciB0aGUgY29sdW1ucykKYGBge3J9CiMgb3JkZXIgc2hvdWxkIGJlIHR3bywgb25lLCB0ZW50aCAoYXMgdGhpcyBzaG93cyB0aGUgbWluLW1heCByYW5nZSBiZXR0ZXIpCmBgYAoKCiMjIDUuIGNyZWF0ZSBhIG5ldyB0YWJsZSB0aGF0IHN0YXJ0cyBhdCAyMm5kIE1hcmNoIChzaW5jZSBgdWtfZGF0YWAgYGluZmVjdGlvbl9kYXRlYCB3ZW50IHVwIHRvIDIxc3QgTWFyY2ggYXQgdGhlIHRpbWUgSSBjcmVhdGVkIHRoaXMgY29kZSkKYGBge3J9CiMgdXNpbmcgb25seSBlc3RpbWF0ZXMgb2YgMSUgZGVhdGggcmF0ZSBhbmQgZ3Jvd3RoIHJhdGUgb2YgZG91YmxpbmcgZXZlcnkgMy00IGRheXMgKHdoaWNoIG1lYW5zIHF1YWRydXBsaW5nIGluIGEgd2VlaykKCnByZWRpY3RvciA8LSBmdW5jdGlvbihwcmV2aW91c192YWx1ZSkgewogICAgcHJlZGljdGVkX3ZhbHVlIDwtIHByZXZpb3VzX3ZhbHVlICogMS4yNQogICAgcmV0dXJuKHByZWRpY3RlZF92YWx1ZSkKICAgIH0KCiMgY3JlYXRlIHByZWRpY3Rpb25zIGZvciBlYWNoIGRhdGUKdHdlbnR5VHdvTWFyY2ggPC0gMS4yNSAqIDM2MDUwMAp0d2VudHlUaHJlZU1hcmNoIDwtIHByZWRpY3Rvcih0d2VudHlUd29NYXJjaCkKdHdlbnR5Rm91ck1hcmNoIDwtIHByZWRpY3Rvcih0d2VudHlUaHJlZU1hcmNoKQp0d2VudHlGaXZlTWFyY2ggPC0gcHJlZGljdG9yKHR3ZW50eUZvdXJNYXJjaCkKdHdlbnR5U2l4TWFyY2ggPC0gcHJlZGljdG9yKHR3ZW50eUZpdmVNYXJjaCkKdHdlbnR5U2V2ZW5NYXJjaCA8LSBwcmVkaWN0b3IodHdlbnR5U2l4TWFyY2gpCnR3ZW50eUVpZ2h0TWFyY2ggPC0gcHJlZGljdG9yKHR3ZW50eVNldmVuTWFyY2gpCnR3ZW50eU5pbmVNYXJjaCA8LSBwcmVkaWN0b3IodHdlbnR5RWlnaHRNYXJjaCkKdGhpcnR5TWFyY2ggPC0gcHJlZGljdG9yKHR3ZW50eU5pbmVNYXJjaCkKdGhpcnR5T25lTWFyY2ggPC0gcHJlZGljdG9yKHRoaXJ0eU1hcmNoKQpvbmVBcHJpbCA8LSBwcmVkaWN0b3IodGhpcnR5T25lTWFyY2gpCnR3b0FwcmlsIDwtIHByZWRpY3RvcihvbmVBcHJpbCkKdGhyZWVBcHJpbCA8LSBwcmVkaWN0b3IodHdvQXByaWwpCmZvdXJBcHJpbCA8LSBwcmVkaWN0b3IodGhyZWVBcHJpbCkKZml2ZUFwcmlsIDwtIHByZWRpY3Rvcihmb3VyQXByaWwpCnNpeEFwcmlsIDwtIHByZWRpY3RvcihmaXZlQXByaWwpCnNldmVuQXByaWwgPC0gcHJlZGljdG9yKHNpeEFwcmlsKQplaWdodEFwcmlsIDwtIHByZWRpY3RvcihzZXZlbkFwcmlsKQpuaW5lQXByaWwgPC0gcHJlZGljdG9yKGVpZ2h0QXByaWwpCnRlbkFwcmlsIDwtIHByZWRpY3RvcihuaW5lQXByaWwpCmVsZXZlbkFwcmlsIDwtIHByZWRpY3Rvcih0ZW5BcHJpbCkKdHdlbHZlQXByaWwgPC0gcHJlZGljdG9yKGVsZXZlbkFwcmlsKQoKdGhpcnRlZW5BcHJpbCA8LSBwcmVkaWN0b3IodHdlbHZlQXByaWwpCmZvdXJ0ZWVuQXByaWwgPC0gcHJlZGljdG9yKHRoaXJ0ZWVuQXByaWwpCmZpZnRlZW5BcHJpbCA8LSBwcmVkaWN0b3IoZm91cnRlZW5BcHJpbCkKc2l4dGVlbkFwcmlsIDwtIHByZWRpY3RvcihmaWZ0ZWVuQXByaWwpCnNldmVudGVlbkFwcmlsIDwtIHByZWRpY3RvcihzaXh0ZWVuQXByaWwpCmVpZ2h0ZWVuQXByaWwgPC0gcHJlZGljdG9yKHNldmVudGVlbkFwcmlsKQpuaW5ldGVlbkFwcmlsIDwtIHByZWRpY3RvcihlaWdodGVlbkFwcmlsKQp0d2VudHlBcHJpbCA8LSBwcmVkaWN0b3IobmluZXRlZW5BcHJpbCkKdHdlbnR5b25lQXByaWwgPC0gcHJlZGljdG9yKHR3ZW50eUFwcmlsKQp0d2VudHl0d29BcHJpbCA8LSBwcmVkaWN0b3IodHdlbnR5b25lQXByaWwpCnR3ZW50eXRocmVlQXByaWwgPC0gcHJlZGljdG9yKHR3ZW50eXR3b0FwcmlsKQp0d2VudHlmb3VyQXByaWwgPC0gcHJlZGljdG9yKHR3ZW50eXRocmVlQXByaWwpCgoKIyBjcmVhdGUgdmVjdG9ycyB0byBwb3B1bGF0ZSB0aGUgY29sdW1ucwpkYXRlIDwtIGFzLkRhdGUoYygiMjAyMC0wMy0yMiIsICIyMDIwLTAzLTIzIiwgIjIwMjAtMDMtMjQiLCAiMjAyMC0wMy0yNSIsICcyMDIwLTAzLTI2JywnMjAyMC0wMy0yNycsICcyMDIwLTAzLTI4JywgJzIwMjAtMDMtMjknLCAnMjAyMC0wMy0zMCcsICcyMDIwLTAzLTMxJywgIjIwMjAtMDQtMDEiLCAiMjAyMC0wNC0wMiIsICIyMDIwLTA0LTAzIiwgIjIwMjAtMDQtMDQiLCAiMjAyMC0wNC0wNSIsICIyMDIwLTA0LTA2IiwgIjIwMjAtMDQtMDciLCAiMjAyMC0wNC0wOCIsICIyMDIwLTA0LTA5IiwgIjIwMjAtMDQtMTAiLCAiMjAyMC0wNC0xMSIsICIyMDIwLTA0LTEyIiwgIjIwMjAtMDQtMTMiLCAiMjAyMC0wNC0xNCIsICIyMDIwLTA0LTE1IiwgIjIwMjAtMDQtMTYiLCAiMjAyMC0wNC0xNyIsICIyMDIwLTA0LTE4IiwgIjIwMjAtMDQtMTkiLCAiMjAyMC0wNC0yMCIsICIyMDIwLTA0LTIxIiwgIjIwMjAtMDQtMjIiLCAiMjAyMC0wNC0yMyIsICIyMDIwLTA0LTI0IikpCmVzdGltYXRlZF9pbmZlY3Rpb25zX25vX2FjdGlvbiA8LSBjKHR3ZW50eVR3b01hcmNoLCB0d2VudHlUaHJlZU1hcmNoLCB0d2VudHlGb3VyTWFyY2gsIHR3ZW50eUZpdmVNYXJjaCx0d2VudHlTaXhNYXJjaCwgdHdlbnR5U2V2ZW5NYXJjaCwgdHdlbnR5RWlnaHRNYXJjaCwgdHdlbnR5TmluZU1hcmNoLCB0aGlydHlNYXJjaCwgdGhpcnR5T25lTWFyY2gsIG9uZUFwcmlsLCB0d29BcHJpbCwgdGhyZWVBcHJpbCwgZm91ckFwcmlsLCBmaXZlQXByaWwsIHNpeEFwcmlsLCBzZXZlbkFwcmlsLCBlaWdodEFwcmlsLCBuaW5lQXByaWwsIHRlbkFwcmlsLCBlbGV2ZW5BcHJpbCwgdHdlbHZlQXByaWwsIHRoaXJ0ZWVuQXByaWwsIGZvdXJ0ZWVuQXByaWwsIGZpZnRlZW5BcHJpbCwgc2l4dGVlbkFwcmlsLCBzZXZlbnRlZW5BcHJpbCwgZWlnaHRlZW5BcHJpbCwgbmluZXRlZW5BcHJpbCwgdHdlbnR5QXByaWwsIHR3ZW50eW9uZUFwcmlsLCB0d2VudHl0d29BcHJpbCwgdHdlbnR5dGhyZWVBcHJpbCwgdHdlbnR5Zm91ckFwcmlsKQoKIyBjcmVhdGUgdGhlIGRhdGEgZnJhbWUKcHJlZGljdGVkX2luZmVjdGlvbnMgPC0gZGF0YS5mcmFtZShkYXRlLCBlc3RpbWF0ZWRfaW5mZWN0aW9uc19ub19hY3Rpb24pCgojIHRpZHkgdGhlIGVzdGltYXRlZF9pbmZlY3Rpb25zIGNvbHVtbgojcHJlZGljdGVkX2luZmVjdGlvbnMgPC0gcHJlZGljdGVkX2luZmVjdGlvbnMgJT4lIG11dGF0ZShlc3RpbWF0ZWRfaW5mZWN0aW9ucz1mb3JtYXQoZXN0aW1hdGVkX2luZmVjdGlvbnMsIGJpZy5tYXJrID0gIiwiKSkKCiMgaW5zcGVjdCB0aGUgZGF0YSBmcmFtZQpwcmVkaWN0ZWRfaW5mZWN0aW9ucwpgYGAKCiMjIDYuIENyZWF0ZSBhbm90aGVyIGRhdGFmcmFtZSB0byBlc3RpbWF0ZSB0aGUgaW1wYWN0IG9mIHNvY2lhbCBkaXN0YW5jaW5nIG9uIHRoZSBlc3RpbWF0ZQpgYGB7cn0KIyBjcmVhdGUgYSBmdW5jdGlvbiB0aGF0IHVzZXMgYSBncm93dGggcmF0ZSBvZiAxLjEyNSAtIGhhbGYgb2YgdGhlIDI1JS4gVGhpcyBpcyB0aGUgZXN0aW1hdGUgZm9yIHRoZSBub3QteWV0LWxvY2tkb3duIHRoYXQgZXhpc3RlZCB1cCB0byAyM3JkIE1hcmNoLiBTbywgdGhlIGVzdGltYXRlIGFzc3VtZXMgdGhhdCB0aGUgc29jaWFsIGRpc3RhbmNpbmcgbWVhc3VyZXMgcmVkdWNlZCB0aGUgaW5mZWN0aW9uIHJhdGUgYnkgYSBoYWxmLgpoYWxmX3ByZWRpY3RvciA8LSBmdW5jdGlvbihwcmV2aW91c192YWx1ZSkgewogICAgcHJlZGljdGVkX3ZhbHVlIDwtIHByZXZpb3VzX3ZhbHVlICogMS4xMjUKICAgIHJldHVybihwcmVkaWN0ZWRfdmFsdWUpCn0KCiMgY3JlYXRlIGEgZnVuY3Rpb24gdGhhdCB1c2VzIGEgZ3Jvd3RoIHJhdGUgb2YgMS4wNjI1IC0gcXVhcnRlciBvZiB0aGUgMjUlLiBUaGlzIGlzIHRoZSBlc3RpbWF0ZWQgaW1wYWN0IG9mIHRoZSBsb2NrZG93biBpbXBsZW1lbnRlZCBieSB0aGUgVUsgZ292ZXJubWVudCBvbiAyM3JkIE1hcmNoIChidXQgc2luY2UgdGhlIGxvY2tkb3duIHdhcyBhbm5vdW5jZWQgaW4gdGhlIGV2ZW5pbmcsIGFuZCBpdCB3b3VsZCB0YWtlIGEgZnVsbCBkYXkgZm9yIGl0cyBlZmZlY3RzIHRvIGJlIGZlbHQgaW4gc3RhdGlzdGljcywgSSB3aWxsIGFzc3VtZSB0aGF0IGl0cyBlZmZlY3RzIGJlZ2FuIG9uIDI1dGggTWFyY2gpLgpsb2NrZG93bl9wcmVkaWN0b3IgPC0gZnVuY3Rpb24ocHJldmlvdXNfdmFsdWUpIHsKICBwcmVkaWN0ZWRfdmFsdWUgPC0gcHJldmlvdXNfdmFsdWUgKiAxLjA2MjUKICByZXR1cm4ocHJlZGljdGVkX3ZhbHVlKQp9CgojIGNyZWF0ZSBwcmVkaWN0aW9ucyBmb3IgZWFjaCBkYXRlCnR3ZW50eVR3b01hcmNoIDwtIDEuMTI1ICogMzYwNTAwCnR3ZW50eVRocmVlTWFyY2ggPC0gaGFsZl9wcmVkaWN0b3IodHdlbnR5VHdvTWFyY2gpCnR3ZW50eUZvdXJNYXJjaCA8LSBoYWxmX3ByZWRpY3Rvcih0d2VudHlUaHJlZU1hcmNoKQp0d2VudHlGaXZlTWFyY2ggPC0gbG9ja2Rvd25fcHJlZGljdG9yKHR3ZW50eUZvdXJNYXJjaCkKdHdlbnR5U2l4TWFyY2ggPC0gbG9ja2Rvd25fcHJlZGljdG9yKHR3ZW50eUZpdmVNYXJjaCkKdHdlbnR5U2V2ZW5NYXJjaCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodHdlbnR5U2l4TWFyY2gpCnR3ZW50eUVpZ2h0TWFyY2ggPC0gbG9ja2Rvd25fcHJlZGljdG9yKHR3ZW50eVNldmVuTWFyY2gpCnR3ZW50eU5pbmVNYXJjaCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodHdlbnR5RWlnaHRNYXJjaCkKdGhpcnR5TWFyY2ggPC0gbG9ja2Rvd25fcHJlZGljdG9yKHR3ZW50eU5pbmVNYXJjaCkKdGhpcnR5T25lTWFyY2ggPC0gbG9ja2Rvd25fcHJlZGljdG9yKHRoaXJ0eU1hcmNoKQpvbmVBcHJpbCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodGhpcnR5T25lTWFyY2gpCnR3b0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihvbmVBcHJpbCkKdGhyZWVBcHJpbCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodHdvQXByaWwpCmZvdXJBcHJpbCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodGhyZWVBcHJpbCkKZml2ZUFwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3Rvcihmb3VyQXByaWwpCnNpeEFwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihmaXZlQXByaWwpCnNldmVuQXByaWwgPC0gbG9ja2Rvd25fcHJlZGljdG9yKHNpeEFwcmlsKQplaWdodEFwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihzZXZlbkFwcmlsKQpuaW5lQXByaWwgPC0gbG9ja2Rvd25fcHJlZGljdG9yKGVpZ2h0QXByaWwpCnRlbkFwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihuaW5lQXByaWwpCmVsZXZlbkFwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3Rvcih0ZW5BcHJpbCkKdHdlbHZlQXByaWwgPC0gbG9ja2Rvd25fcHJlZGljdG9yKGVsZXZlbkFwcmlsKQoKdGhpcnRlZW5fQXByaWwgPC0gbG9ja2Rvd25fcHJlZGljdG9yKHR3ZWx2ZUFwcmlsKQpmb3VydGVlbl9BcHJpbCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodGhpcnRlZW5fQXByaWwpCmZpZnRlZW5fQXByaWwgPC0gbG9ja2Rvd25fcHJlZGljdG9yKGZvdXJ0ZWVuX0FwcmlsKQpzaXh0ZWVuX0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihmaWZ0ZWVuX0FwcmlsKQpzZXZlbnRlZW5fQXByaWwgPC0gbG9ja2Rvd25fcHJlZGljdG9yKHNpeHRlZW5fQXByaWwpCmVpZ2h0ZWVuX0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihzZXZlbnRlZW5fQXByaWwpCm5pbmV0ZWVuX0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihlaWdodGVlbl9BcHJpbCkKdHdlbnR5X0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3RvcihuaW5ldGVlbl9BcHJpbCkKdHdlbnR5b25lX0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3Rvcih0d2VudHlfQXByaWwpCnR3ZW50eXR3b19BcHJpbCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodHdlbnR5b25lX0FwcmlsKQp0d2VudHl0aHJlZV9BcHJpbCA8LSBsb2NrZG93bl9wcmVkaWN0b3IodHdlbnR5dHdvX0FwcmlsKQp0d2VudHlmb3VyX0FwcmlsIDwtIGxvY2tkb3duX3ByZWRpY3Rvcih0d2VudHl0aHJlZV9BcHJpbCkKCiMgY3JlYXRlIHZlY3RvcnMgdG8gcG9wdWxhdGUgdGhlIGNvbHVtbnMKZGF0ZSA8LSBhcy5EYXRlKGMoIjIwMjAtMDMtMjIiLCAiMjAyMC0wMy0yMyIsICIyMDIwLTAzLTI0IiwgIjIwMjAtMDMtMjUiLCAnMjAyMC0wMy0yNicsJzIwMjAtMDMtMjcnLCAnMjAyMC0wMy0yOCcsICcyMDIwLTAzLTI5JywgJzIwMjAtMDMtMzAnLCAnMjAyMC0wMy0zMScsICIyMDIwLTA0LTAxIiwgIjIwMjAtMDQtMDIiLCAiMjAyMC0wNC0wMyIsICIyMDIwLTA0LTA0IiwgIjIwMjAtMDQtMDUiLCAiMjAyMC0wNC0wNiIsICIyMDIwLTA0LTA3IiwgIjIwMjAtMDQtMDgiLCAiMjAyMC0wNC0wOSIsICIyMDIwLTA0LTEwIiwgIjIwMjAtMDQtMTEiLCAiMjAyMC0wNC0xMiIsICIyMDIwLTA0LTEzIiwgIjIwMjAtMDQtMTQiLCAiMjAyMC0wNC0xNSIsICIyMDIwLTA0LTE2IiwgIjIwMjAtMDQtMTciLCAiMjAyMC0wNC0xOCIsICIyMDIwLTA0LTE5IiwgIjIwMjAtMDQtMjAiLCAiMjAyMC0wNC0yMSIsICIyMDIwLTA0LTIyIiwgIjIwMjAtMDQtMjMiLCAiMjAyMC0wNDAyNCIpKQplc3RpbWF0ZWRfaW5mZWN0aW9uc19sb2NrZG93biA8LSBjKHR3ZW50eVR3b01hcmNoLCB0d2VudHlUaHJlZU1hcmNoLCB0d2VudHlGb3VyTWFyY2gsIHR3ZW50eUZpdmVNYXJjaCx0d2VudHlTaXhNYXJjaCwgdHdlbnR5U2V2ZW5NYXJjaCwgdHdlbnR5RWlnaHRNYXJjaCwgdHdlbnR5TmluZU1hcmNoLCB0aGlydHlNYXJjaCwgdGhpcnR5T25lTWFyY2gsIG9uZUFwcmlsLCB0d29BcHJpbCwgdGhyZWVBcHJpbCwgZm91ckFwcmlsLCBmaXZlQXByaWwsIHNpeEFwcmlsLCBzZXZlbkFwcmlsLCBlaWdodEFwcmlsLCBuaW5lQXByaWwsIHRlbkFwcmlsLCBlbGV2ZW5BcHJpbCwgdHdlbHZlQXByaWwsIHRoaXJ0ZWVuX0FwcmlsLCBmb3VydGVlbl9BcHJpbCwgZmlmdGVlbl9BcHJpbCwgc2l4dGVlbl9BcHJpbCwgc2V2ZW50ZWVuX0FwcmlsLCBlaWdodGVlbl9BcHJpbCwgbmluZXRlZW5fQXByaWwsIHR3ZW50eV9BcHJpbCwgdHdlbnR5b25lX0FwcmlsLCB0d2VudHl0d29fQXByaWwsIHR3ZW50eXRocmVlX0FwcmlsLCB0d2VudHlmb3VyX0FwcmlsKQoKIyBjcmVhdGUgdGhlIGRhdGEgZnJhbWUKbG9ja2Rvd25faW5mZWN0aW9uX3JhdGVzIDwtIGRhdGEuZnJhbWUoZGF0ZSwgZXN0aW1hdGVkX2luZmVjdGlvbnNfbG9ja2Rvd24pCgojIHRpZHkgdGhlIGVzdGltYXRlZF9pbmZlY3Rpb25zIGNvbHVtbgojbG9ja2Rvd25faW5mZWN0aW9uX3JhdGVzIDwtIGxvY2tkb3duX2luZmVjdGlvbl9yYXRlcyAlPiUgbXV0YXRlKGVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duPWZvcm1hdChlc3RpbWF0ZWRfaW5mZWN0aW9uc19sb2NrZG93biwgc2NpZW50aWZpYyA9IEZBTFNFKSkKCiMgaW5zcGVjdCB0aGUgZGF0YSBmcmFtZQpsb2NrZG93bl9pbmZlY3Rpb25fcmF0ZXMKCmBgYAoKICMjIDcuIE1lcmdlIHRoZSB0d28gcHJlZGljdGlvbiBkYXRhZnJhbWVzCmBgYHtyfQpjb21wYXJlZF9pbmZlY3Rpb25zIDwtIHByZWRpY3RlZF9pbmZlY3Rpb25zICU+JSBiaW5kX2NvbHMoZXN0aW1hdGVkX2luZmVjdGlvbnNfbG9ja2Rvd249bG9ja2Rvd25faW5mZWN0aW9uX3JhdGVzJGVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duKQoKY29tcGFyZWRfaW5mZWN0aW9ucwoKYGBgCgojIyA4LiBUaWR5IHRoZSBkYXRhCmBgYHtyfQojY29tcGFyZWRfaW5mZWN0aW9ucyA8LSBjb21wYXJlZF9pbmZlY3Rpb25zICU+JSBtdXRhdGUoZXN0aW1hdGVkX2luZmVjdGlvbnM9Zm9ybWF0KGVzdGltYXRlZF9pbmZlY3Rpb25zLCBiaWcubWFyayA9ICIsIikpCiNjb21wYXJlZF9pbmZlY3Rpb25zIDwtIGNvbXBhcmVkX2luZmVjdGlvbnMgJT4lIG11dGF0ZShlc3RpbWF0ZWRfaW5mZWN0aW9uc19sb2NrZG93bj1hcy5udW1lcmljKGVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duKSkKI2NvbXBhcmVkX2luZmVjdGlvbnMgPC0gY29tcGFyZWRfaW5mZWN0aW9ucyAlPiUgbXV0YXRlKGVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duPWZvcm1hdChlc3RpbWF0ZWRfaW5mZWN0aW9uc19sb2NrZG93biwgYmlnLm1hcmsgPSAiLCIpKQpjb21wYXJlZF9pbmZlY3Rpb25zCmBgYAoKVGhlIGFib3ZlIHRhYmxlIHNob3dzIGEgaHVnZSBwb3NzaWJsZSBlZmZlY3Qgb2YgbG9ja2Rvd24sIGJ1dCBzdGlsbCB0aGUgbnVtYmVyIG9mIGluZmVjdGlvbnMgaXMgaW4gc2V2ZW4gZmlndXJlcy4gSG93ZXZlciwgdGhpcyBkb2VzIG5vdCBpbmRpY2F0ZSBob3cgbWFueSBwZW9wbGUgbWlnaHQgYmUgaW5mZWN0ZWQgYXQgYW55IGdpdmVuIHRpbWUuIFJhdGhlciwgaXQgZXN0aW1hdGVzIGhvdyBtYW55IHBlb3BsZSBtaWdodCBoYXZlIGJlZW4gaW5mZWN0ZWQgaW4gdG90YWwsIGFuZCBzbyBpbmNsdWRlcyBwZW9wbGUgd2hvIG5vIGxvbmdlciBoYXZlIHRoZSBkaXNlYXNlICh0aGF0IGlzLCBwZW9wbGUgd2hvIGhhdmUgcmVjb3ZlcmVkIG9yIGRpZWQpLgoKIyMgOS4gUHJlZGljdGVkIGRlYXRocyBiYXNlZCBvbiB0aGVzZSBlc3RpbWF0ZXMKV29ya2luZyBiYWNrd2FyZHMgZnJvbSB0aGVzZSBlc3RpbWF0ZXMsIGNvbXBhcmUgdGhlIHByZWRpY3RlZCBkZWF0aHMuIApgYGB7cn0KIyBmaXJzdCwgcHV0IHRoZSBjb2x1bW5zIGJhY2sgdG8gbnVtZXJpYyBmb3JtYXQKI2NvbXBhcmVkX2luZmVjdGlvbnNfYW5kX2RlYXRocyA8LSBjb21wYXJlZF9pbmZlY3Rpb25zICU+JSBtdXRhdGUoZXN0aW1hdGVkX2luZmVjdGlvbnM9YXMubnVtZXJpYyhlc3RpbWF0ZWRfaW5mZWN0aW9ucykpCgpjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHMgPC0gY29tcGFyZWRfaW5mZWN0aW9ucyAlPiUgbXV0YXRlKGVzdGltYXRlZF9kZWF0aHNfbm9fYWN0aW9uPTAuMDEqZXN0aW1hdGVkX2luZmVjdGlvbnNfbm9fYWN0aW9uKQpjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHMgPC0gY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzICU+JSBtdXRhdGUoZXN0aW1hdGVkX2RlYXRoc19sb2NrZG93bj0wLjAxKmVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duKQpjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHMKYGBgCk5vdGUgdGhhdCB0aGUgYGVzdGltYXRlc19kZWF0aHNgIGFuZCBgZXN0aW1hdGVkX2RlYXRoc19sb2NrZG93bmAgY29sdW1ucyBhcmUgbm90IGVzdGltYXRlcyBmb3IgZGVhdGhzIG9uIG9yIHVwIHRvIHRoZSBkYXRlIGluIHRoZSByZWxldmFudCByb3cuIEl0IGlzIGFudGljaXBhdGVkIHRoYXQgZGVhdGhzIHdvdWxkIG9jY3VyIHNvbWUgZGF5cyBvciB3ZWVrcyBhZnRlciB0aGUgZGF0ZSBnaXZlbiBpbiB0aGUgdGFibGUuIEZvciBleGFtcGxlLCBpZiB0aGUgcm93IGZvciAyMDIwLTA0LTAxIHNob3dzIGBlc3RpbWF0ZWRfZGVhdGhzX2xvY2tkb3duYCBvZiA4MzM2LjcwMywgdGhhdCBkb2Vzbid0IG1lYW4gODMzNi43MDMgcGVvcGxlIHdvdWxkIGhhdmUgZGllZCBieSAyMDIwLTA0LTAxLiBSYXRoZXIsIHRoYXQgZmlndXJlIHdvdWxkIG9jY3VyIGFyb3VuZCB0d28gd2Vla3MgYWZ0ZXIgMjAyMC0wNC0wMSAoc28sIGFwcHJveGltYXRlbHkgMjAyMC0wNC0xNSkuIFNvLCB0aGlzIHN1Z2dlc3RzIGFuIGFkZGl0aW9uYWwgY29sdW1uIG1pZ2h0IGJlIHVzZWZ1bCAoZGF0ZSBvZiBwcmVkaWN0ZWQgZGVhdGhzKQp5bWQoJzIwMTktMTItMDEnKSAlbSslIHBlcmlvZCgiMSBtb250aCIpCgpgYGB7cn0KY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzIDwtIGNvbXBhcmVkX2luZmVjdGlvbnNfYW5kX2RlYXRocyAlPiUgbXV0YXRlKGRlYXRoX2RhdGVfMTRfZGF5cz1hcy5EYXRlKGRhdGUgKyBkYXlzKDE0KSkpCmNvbXBhcmVkX2luZmVjdGlvbnNfYW5kX2RlYXRoc19kYXRlcyA8LSBjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHNfZGF0ZXMgJT4lIG11dGF0ZShkZWF0aF9kYXRlXzdfZGF5cz1hcy5EYXRlKGRhdGUgKyBkYXlzKDcpKSkKCiMgYWRkIGEgY29sdW1uIHRvIHJldmlldyB0aGUgcmVzdWx0cyBvbiBhIGRhaWx5IGJhc2lzLgphc3Nlc3MgPC0gYygiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiLCAiTkEiKQpjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHNfZGF0ZXMgPC0gY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzICU+JSBtdXRhdGUoZm91cnRlZW5fZGF5X2Fzc2Vzc21lbnQgPSBhc3Nlc3MpCgpjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHNfZGF0ZXMgPC0gY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzICU+JSBtdXRhdGUoZm91cnRlZW5fZGF5X2Fzc2Vzc21lbnQ9cmVwbGFjZShmb3VydGVlbl9kYXlfYXNzZXNzbWVudCwgZGVhdGhfZGF0ZV8xNF9kYXlzPT1jKCIyMDIwLTA0LTA1IiwgIjIwMjAtMDQtMDYiLCAiMjAyMC0wNC0wNyIsICIyMDIwLTA0LTA4IiwgIjIwMjAtMDQtMDkiLCAiMjAyMC0wNC0xMCIsICIyMDIwLTA0LTExIiwgIjIwMjAtMDQtMTIiLCAiMjAyMC0wNC0xMyIsICIyMDIwLTA0LTE0IiwgIjIwMjAtMDQtMTUiLCAiMjAyMC0wNC0xNiIsICIyMDIwLTA0LTE3IiwgIjIwMjAtMDQtMTgiLCAiMjAyMC0wNC0xOSIsICIyMDIwLTA0LTIwIiwgIjIwMjAtMDQtMjEiKSwgYygiQXMgb2YgMjAyMC0wNC0wNSwgdGhlIGFjdHVhbCBkZWF0aCB0b2xsIHdhcyA0MzEzIiwgIkFzIG9mIDIwMjAtMDQtMDYsIHRoZSBhY3R1YWwgZGVhdGggdG9sbCB3YXMgNDkzNCIsICJBcyBvZiAyMDIwLTA0LTA3LCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDUzNzMiLCAiQXMgb2YgMjAyMC0wNC0wOCwgdGhlIGFjdHVhbCBkZWF0aCB0b2xsIHdhcyA2MTU5IiwgIkFzIG9mIDIwMjAtMDQtMDksIHRoZSBhY3R1YWwgZGVhdGggdG9sbCB3YXMgNzA5NyIsICJBcyBvZiAyMDIwLTA0LTEwLCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDc5NzgiLCJBcyBvZiAyMDIwLTA0LTExLCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDg5NTgiLCJBcyBvZiAyMDIwLTA0LTEyLCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDk4NzUiLCAiQXMgb2YgMjAyMC0wNC0xMywgdGhlIGFjdHVhbCBkZWF0aCB0b2xsIHdhcyAxMDYxMiIsICJBcyBvZiAyMDIwLTA0LTE0LCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDExMzI5IiwgIkFzIG9mIDIwMjAtMDQtMTUsIHRoZSBhY3R1YWwgZGVhdGggdG9sbCB3YXMgMTIxMDciLCAiQXMgb2YgMjAyMC0wNC0xNiwgdGhlIGFjdHVhbCBkZWF0aCB0b2xsIHdhcyAxMjg2OCIsICJBcyBvZiAyMDIwLTA0LTE3LCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDEzNzI5IiwgIkFzIG9mIDIwMjAtMDQtMTgsIHRoZSBhY3R1YWwgZGVhdGggdG9sbCB3YXMgMTQ1NzYiLCAiQXMgb2YgMjAyMC0wNC0xOSwgdGhlIGFjdHVhbCBkZWF0aCB0b2xsIHdhcyAxNTQ2NCIsICJBcyBvZiAyMDIwLTA0LTIwLCB0aGUgYWN0dWFsIGRlYXRoIHRvbGwgd2FzIDE2MDYwIiwgIkFzIG9mIDIwMjAtMDQtMjEsIHRoZSBhY3R1YWwgZGVhdGggdG9sbCB3YXMgMTY1MDkiKSkpCgojcmVvcmRlciB0aGUgY29sdW1ucwpuZXdfb3JkZXIgPC0gYygiZGF0ZSIsICJlc3RpbWF0ZWRfaW5mZWN0aW9uc19ub19hY3Rpb24iLCAiZXN0aW1hdGVkX2luZmVjdGlvbnNfbG9ja2Rvd24iLCAiZXN0aW1hdGVkX2RlYXRoc19ub19hY3Rpb24iLCAgImVzdGltYXRlZF9kZWF0aHNfbG9ja2Rvd24iLCAiZGVhdGhfZGF0ZV8xNF9kYXlzIiwgImZvdXJ0ZWVuX2RheV9hc3Nlc3NtZW50IiwgImRlYXRoX2RhdGVfN19kYXlzIikKCmNvbXBhcmVkX2luZmVjdGlvbnNfYW5kX2RlYXRoc19kYXRlcyA8LSBjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHNfZGF0ZXNbLCBuZXdfb3JkZXJdCgojbmFtZXMgPC0gY29sbmFtZXMoY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzKQojbmFtZXMKY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzCmBgYAoKSW4gd2hhdCB3YXlzIGNvdWxkIHRoZXNlIGVzdGltYXRlcyBhbmQgcHJlZGljdGlvbnMgZ28gd3Jvbmc/IE9yLCB3aGF0IHBhcnRzIG9mIHRoZSBkYXRhIGNvdWxkIGJlIGluYWNjdXJhdGU/CiogZXN0aW1hdGUgb2YgMSUgZGVhdGggcmF0ZSAKKiBlc3RpbWF0ZSBvZiB0aW1lIHRha2VuIGZvciBsb2NrZG93biB0byBoYXZlIGFuIGVmZmVjdCAoSSd2ZSBzYWlkIDE0LTIxIGRheXMpLiBOb3RlIHRoYXQgYGRlYXRoX2RhdGVfN19kYXlzYCBzaG93cyB0aGUgZGF0ZSBpZiBpdCB0YWtlcyAyMSBkYXlzIHRvIGhhdmUgYW4gaW1wYWN0LiAKKiBlc3RpbWF0ZSBvZiBkYWlseSBncm93dGggcmF0ZXMgZm9yIG1pbmltYWwgc29jaWFsIGRpc3RhbmNpbmcgKDEuMTI1KSBhbmQgbG9ja2Rvd24gKDEuMDYyNSkKCiogdXBkYXRlIDZ0aCBBcHJpbCAyMDIwIC0gaXQgbG9va3MgbGlrZSBteSBwcmVkaWN0aW9ucyBtYXkgYmUgYSBkYXkgb3IgdHdvIG91dCBvZiBzeW5jaCB3aXRoIHRoZSBzdGF0cy4gSXQncyBoYXJkIHRvIHRlbGwsIGFzIHRoZSBudW1iZXIgZm9yIGxvY2tkb3duIGFuZCBubyBhY3Rpb24gYXJlIGZhaXJseSBzaW1pbGFyIGF0IHRoaXMgcG9pbnQuIFRoaXMgbWVhbnMgdGhhdCBpdCBjYW4gYmUgZGlmZmljdWx0IHRvIG1ha2UgYW4gYXNzZXNzbWVudDogaWYgdGhlIGFjdHVhbCBkZWF0aCB0b2xsIGlzIGxvd2VyIHRoYW4gdGhlIGVzdGltYXRlZF9kZWF0aHNfbm9fYWN0aW9uIGNvbHVtbiwgaXMgdGhhdCBkdWUgdG8gdGhlIGxvY2tkb3duIG9yIHRoZSBmYWN0IHRoYXQgaXQgaXMgYSBkYXkgb3IgdHdvIGJlaGluZD8gSG93ZXZlciwgYnkgYXJvdW5kIDEwdGggQXByaWwgdGhlcmUgc2hvdWxkIGJlIGEgY2xlYXJlciBwaWN0dXJlLiAKCiogdXBkYXRlIDEwdGggQXByaWwgMjAyMCAtIGl0IG5vdyBsb29rcyBsaWtlIG15IHByZWRpY3Rpb25zIG1pZ2h0IGJlIDMgb3IgNCBkYXlzIG91dCBvZiBzeW5jaCB3aXRoIHRoZSBzdGF0cy4gTG9vayBhdCB0aGUgYGRlYXRoX2RhdGVfMTRfZGF5c2AgY29sdW1uLCB0aGVuIGFkZCA0IGRheXMuIFRoZW4gbG9vayBhdCB0aGUgYGVzdGltYXRlZF9kZWF0aHNfbG9ja2Rvd25gIGNvbHVtbi4gVGhpcyBzZWVtcyB0byBiZSBjbG9zZXIgdG8gdGhlIGFjdHVhbCBkZWF0aCB0b2xsLiAKKiB1cGRhdGUgMTF0aCBBcHJpbCAyMDIwOiBob3NwaXRhbCBkZWF0aHMgdmVyc3VzIHRvdGFsIGRlYXRocy4gTXkgZmlndXJlcyBhcmUgZm9yIHRvdGFsIGRlYXRocywgYnV0IHRoZSBVSyBwcm92aWRlcyBmaWd1cmVzIGZvciBob3NwaXRhbCBkZWF0aHMuIE9uZSBlc3RpbWF0ZSBJIHNhdyB3YXMgdGhhdCB0aGVyZSB3ZXJlIG92ZXIgODAwMCBkZWF0aHMgaW4gaG9zcGl0YWwsIHBsdXMgYW4gYWRkaXRpb25hbCAxMDAwIGluIGNhcmUgaG9tZXMgdGhhdCB3ZXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgVUsgZmlndXJlcy4gSSdtIG5vdCBzdXJlIHdoZXRoZXIgb3Igbm90IHRoZSBXSE8gZmlndXJlcyBjb3ZlciBvbmx5IGhvc3BpdGFsIGRlYXRocywgYnV0IGlmIHRoZXkgZG8gdGhlbiBpdCB3b3VsZCBoYXZlIGFuIGltcGFjdCBvbiBteSBwcmVkaWN0aW9ucy4KKiB1cGRhdGUgMTJ0aCBBcHJpbCAyMDIwIC0gaXQgbm93IGxvb2tzIGxpa2UgbXkgcHJlZGljdGlvbnMgYXJlIDUtNiBkYXlzIG91dCBvZiBzeW5jaCB3aXRoIHRoZSBzdGF0cy4gU28sIGxvb2sgYXQgdGhlIGBkZWF0aF9kYXRlXzE0X2RheXNgIGNvbHVtbiwgdGhlbiBhZGQgNSBvciA2IGRheXMuIAoqIHVwZGF0ZSAxM3RoIEFwcmlsIDIwMjAgLSB0aGUgbGF0ZXN0IGZpZ3VyZXMgZnJvbSB0aGUgW09mZmljZSBmb3IgTmF0aW9uYWwgU3RhdGlzdGljc10oaHR0cHM6Ly93d3cub25zLmdvdi51ay9wZW9wbGVwb3B1bGF0aW9uYW5kY29tbXVuaXR5L2JpcnRoc2RlYXRoc2FuZG1hcnJpYWdlcy9kZWF0aHMvYnVsbGV0aW5zL2RlYXRoc3JlZ2lzdGVyZWR3ZWVrbHlpbmVuZ2xhbmRhbmR3YWxlc3Byb3Zpc2lvbmFsL3dlZWtlbmRpbmczYXByaWwyMDIwKSBzdWdnZXN0IHRoYXQgLSBpbiBFbmdsYW5kIGFuZCBXYWxlcywgYXQgbGVhc3QgLSBkZWF0aHMgb3V0c2lkZSBob3NwaXRhbHMgYWNjb3VudCBmb3IgYXJvdW5kIDEwJSBvZiBhbGwgQ292aWQtMTktcmVsYXRlZCBkZWF0aHMuIFdoaWxzdCBJIGRvIG5vdCBoYXZlIHRoZSBub24taG9zcGl0YWwgZmlndXJlcyBmb3IgU2NvdGxhbmQgb3IgTm9ydGhlcm4gSXJlbGFuZCwgSSBoYXZlIG5vIHJlYXNvbiB0byBiZWxpZXZlIHRoZXkgd291bGQgYmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBFbmdsYW5kIGFuZCBXYWxlcy4gU28sIEkgd2lsbCBhc3N1bWUgdGhhdCAxMCUgb2YgYWxsIENvdmlkLTE5LXJlbGF0ZWQgZGVhdGhzIGluIHRoZSBVSyBoYXBwZW4gb3V0c2lkZSBvZiBob3NwaXRhbHMuIFRoaXMgaGFzIGFuIGltcGFjdCBvbiBob3cgb25lIHJlYWRzIHRoZSBmaWd1cmVzIGluIG15IHByb2plY3QuIFRoZSBmaWd1cmVzIEkgdXNlIGluIHRoaXMgcHJvamVjdCBhcmUgZnJvbSB0aGUgV0hPLCB3aGljaCBjb3VudHMgaG9zcGl0YWwgZGVhdGhzIG9ubHkuIFRoZXJlZm9yZSwgZm9yIGFueSBnaXZlbiBkYXRlLCB0aGUgbnVtYmVyIG9mIGRlYXRocyBpbiBteSBkYXRhc2V0cyBzaG91bGQgYmUgY29uc2lkZXJlZCB0byBiZSBvbmx5IDkwJSBvZiB0aGUgdHJ1ZSB0b3RhbC4gRm9yIGluc3RhbmNlLCB3aGVyZSBteSBkYXRhc2V0cyBzdGF0ZSB0aGF0IHRoZSBkZWF0aCB0b2xsIG9uIDExdGggQXByaWwgd2FzIDg5NTgsIHdlIGNhbiBlc3RpbWF0ZSB0aGF0IHRoZSB0cnVlIGRlYXRoIHRvbGwgd2FzIGFjdHVhbGx5IGFyb3VuZCAxMCwwMDAuCiogdXBkYXRlIDE3dGggQXByaWwgLSB0aGUgZmlndXJlcyBhcmUgNi03IGRheXMgb3V0LgoKYGBge3IsIGZpZy53aWR0aD0gOS41LCBmaWcuaGVpZ2h0PTZ9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmluZmVjdGlvbnNDb21wYXJpc29uTGluZSA8LSBnZ3Bsb3QoY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzLCBhZXMoeD1kYXRlKSkgKyBnZW9tX2xpbmUoYWVzKHk9ZXN0aW1hdGVkX2luZmVjdGlvbnNfbm9fYWN0aW9uKSwgY29sID0gInN0ZWVsYmx1ZSIpICsgZ2VvbV9saW5lKGFlcyh5PWVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duKSwgY29sPSJkYXJrcmVkIikgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPWxhYmVsX2NvbW1hKCkpICsgZ2VvbV90ZXh0KGFlcyh4PWFzLkRhdGUoIjIwMjAtMDQtMTMiKSwgeSA9IDUwMDAwMDAwLCBsYWJlbD0iTm8gYWN0aW9uIikpICsgZ2VvbV90ZXh0KHg9YXMuRGF0ZSgiMjAyMC0wNC0xMyIpLCB5ID0gNTAwMDAwMCwgbGFiZWw9IkxvY2tkb3duIikgKyBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgaW5mZWN0aW9ucyAobG9ja2Rvd24gdmVyc3VzIG5vIGFjdGlvbikiLCB4PSdEYXRlJywgeT0nUHJlZGljdGVkIEluZmVjdGlvbnMnKSArIHRoZW1lX2NsYXNzaWMoKQppbmZlY3Rpb25zQ29tcGFyaXNvbkxpbmUKIApgYGAKCmBgYHtyLCBmaWcud2lkdGg9IDkuNSwgZmlnLmhlaWdodD02fQpkZWF0aHNDb21wYXJpc29uTGluZSA8LSBnZ3Bsb3QoY29tcGFyZWRfaW5mZWN0aW9uc19hbmRfZGVhdGhzX2RhdGVzLCBhZXMoeD1kZWF0aF9kYXRlXzdfZGF5cykpICsgZ2VvbV9saW5lKGFlcyh5PWVzdGltYXRlZF9kZWF0aHNfbm9fYWN0aW9uKSwgY29sID0gInN0ZWVsYmx1ZSIpICsgZ2VvbV9saW5lKGFlcyh5PWVzdGltYXRlZF9kZWF0aHNfbG9ja2Rvd24pLCBjb2w9ImRhcmtyZWQiKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9bGFiZWxfY29tbWEoKSkgKyBnZW9tX3RleHQoYWVzKHg9YXMuRGF0ZSgiMjAyMC0wNC0yMSIpLCB5ID0gNTAwMDAwLCBsYWJlbD0iTm8gYWN0aW9uIikpICsgZ2VvbV90ZXh0KHg9YXMuRGF0ZSgiMjAyMC0wNC0yMSIpLCB5ID0gNTAwMDAsIGxhYmVsPSJMb2NrZG93biIpICsgbGFicyh0aXRsZT0iUHJlZGljdGVkIERlYXRocyAobG9ja2Rvd24gdmVyc3VzIG5vIGFjdGlvbikiLCBzdWJ0aXRsZT0iZXN0aW1hdGVzIHRoYXQgaXQgdGFrZXMgMyB3ZWVrcyBmb3IgbWVhc3VyZXMgdG8gaW1wYWN0IGRlYXRocyIsIHg9J0RhdGUnLCB5PSdQcmVkaWN0ZWQgRGVhdGhzJykgKyB0aGVtZV9jbGFzc2ljKCkKZGVhdGhzQ29tcGFyaXNvbkxpbmUKYGBgCgpgYGB7cn0KZGVhdGhzQ29tcGFyaXNvbkxpbmUgPC0gZ2dwbG90KGNvbXBhcmVkX2luZmVjdGlvbnNfYW5kX2RlYXRoc19kYXRlcywgYWVzKHg9ZGVhdGhfZGF0ZV8xNF9kYXlzKSkgKyBnZW9tX2xpbmUoYWVzKHk9ZXN0aW1hdGVkX2RlYXRoc19ub19hY3Rpb24pLCBjb2wgPSAic3RlZWxibHVlIikgKyBnZW9tX2xpbmUoYWVzKHk9ZXN0aW1hdGVkX2RlYXRoc19sb2NrZG93biksIGNvbD0iZGFya3JlZCIpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1sYWJlbF9jb21tYSgpKSArIGdlb21fdGV4dChhZXMoeD1hcy5EYXRlKCIyMDIwLTA0LTI4IiksIHkgPSA1MDAwMDAsIGxhYmVsPSJObyBhY3Rpb24iKSkgKyBnZW9tX3RleHQoeD1hcy5EYXRlKCIyMDIwLTA0LTI4IiksIHkgPSA1MDAwMCwgbGFiZWw9IkxvY2tkb3duIikgKyBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgRGVhdGhzIChsb2NrZG93biB2ZXJzdXMgbm8gYWN0aW9uKSIsIHN1YnRpdGxlPSJlc3RpbWF0ZXMgdGhhdCBpdCB0YWtlcyAyIHdlZWtzIGZvciBtZWFzdXJlcyB0byBpbXBhY3QgZGVhdGhzIiwgeD0nRGF0ZScsIHk9J1ByZWRpY3RlZCBEZWF0aHMnKSArIHRoZW1lX2NsYXNzaWMoKQpkZWF0aHNDb21wYXJpc29uTGluZQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9IDkuNSwgZmlnLmhlaWdodD02fQoKbGlicmFyeShwbG90bHkpCmNhc2VzRGVhdGhzIDwtIGdncGxvdChjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHNfZGF0ZXMsIGFlcyh4PWVzdGltYXRlZF9pbmZlY3Rpb25zX2xvY2tkb3duLCB5PWVzdGltYXRlZF9kZWF0aHNfbG9ja2Rvd24pKSArIGdlb21fcG9pbnQoKQpjYXNlc0RlYXRocwppbnRlcmFjdGl2ZSA8LSBnZ3Bsb3RseShjYXNlc0RlYXRocykKCiMgZmlnIDwtIGludGVyYWN0aXZlICU+JQojICAgcGxvdF9seSgKIyAgICAgeCA9IH54LAojICAgICB5ID0gfnksCiMgICAgIGZyYW1lID0gfmYsCiMgICAgIHR5cGUgPSAnc2NhdHRlcicsCiMgICAgIG1vZGUgPSAnbWFya2VycycsCiMgICAgIHNob3dsZWdlbmQgPSBGCiMgICApCmZpZyA8LSBjb21wYXJlZF9pbmZlY3Rpb25zX2FuZF9kZWF0aHNfZGF0ZXMgJT4lIHBsb3RfbHkoeD1+ZXN0aW1hdGVkX2luZmVjdGlvbnNfbG9ja2Rvd24sIHk9fmVzdGltYXRlZF9kZWF0aHNfbG9ja2Rvd24sIGZyYW1lID0gfmRhdGUsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGU9J21hcmtlcnMnKQoKCiMgZmlnIDwtIGZpZyAlPiUgbGF5b3V0KAojICAgICB4YXhpcyA9IGxpc3QoCiMgICAgICAgdHlwZSA9ICJsb2ciCiMgICAgICkKIyAgICkKIAoKZmlnMiA8LSBmaWcgJT4lIGFuaW1hdGlvbl9zbGlkZXIoY3VycmVudHZhbHVlPWxpc3QocHJlZml4ID0gIkRhdGUiLCBmb250ID0gbGlzdChjb2xvcj0ncmVkJykpKQpmaWcyCgpgYGAKCg==